/*
 * Copyright (C) 2022 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef DATABASE_H
#define DATABASE_H

#include "types.h"
#include <QObject>
#include <QSqlDatabase>
#include <QSettings>

class DataBase : public QObject
{
    Q_OBJECT
public:
    explicit DataBase(const QString &databasePath,
                      QObject *parent = nullptr);
    ~DataBase();

    enum ItemType {
        Icon = 1,
        Group,
        Container,
        Widget
    };

    ///
    /// \brief openDatabase：打开数据库
    /// \return 成功 or 失败
    ///
    bool openDatabase();
    ///
    /// \brief 关闭数据库
    ///
    void closeDataBase();

public:
    ///
    /// \brief queryAllItemData：查询系统中全部的 Item 数据
    /// \warning 注意指针数组一定要进行释放
    /// \return 存储所有应用指针的map
    ///
    UKUI::ItemMap queryAllItemData() const;
    ///
    /// \brief queryAllSetData：查询可以翻页的 Sets 中全部的 Item 数据
    /// \return 存储 Sets 中所有的 Item 指针 <setId, <Set第一页的idlist，Set第二页的idlist>>
    ///
    QMap<int, QList<QList<int>>> queryAllItemIdsInSet();

    QMap<int, QList<int>> queryAllItemIdsInHomeScreen();    
    bool addAppItem(const UKUI::IconItem &item);
    QVariant addWidgetItem(const UKUI::Widget &item);
    bool addContainerItem(const UKUI::ContainerItem &item, const QList<QList<int>> &itemIdsInContainer);
    QVariant addGroupItem(const UKUI::GroupItem &item, const QList<QList<int>> &itemIdsInGroup);
    bool addHomeScreenPage(int pageId, const QList<int> &sequence);
    bool deleteHomeScreenPage(int pageId);
    bool updateHomeScreenPage(int pageId, const QList<int> &sequence);
    bool updateAppItem(const UKUI::IconItem &item);

    ///
    /// \brief setFlipSetData：修改 container 或者 group 里的应用列表
    /// \param setId：container 或 group 的 id
    /// \param sequence：应用列表
    ///
    bool setFlipSetData(quint32 setId, const QList<QList<quint32>> &sequence);

    bool updateSetData(int setId, const UKUI::ItemIdsPage &itemIdsInPage);
    bool updateSetName(int setId, const QString &name);

    ///
    /// \brief setPageData   修改 page 页的数据
    /// \param pageId           page 页的 id
    /// \param sequence         page 页即将存储的应用列表
    ///
    bool setPageData(quint32 pageId, const QList<quint32> &sequence);

    bool setPageData(int pageId, const QList<int> &sequence);

    ///
    /// \brief queryItemIdFromSet 查询itemId是否在set中
    /// \param pageId
    /// \param itemId
    /// \return
    ///
    bool queryPageItemIdFromSet(int itemId);
    ///
    /// \brief queryItemIdFromList()
    /// \param itemId
    /// \return
    ///
    bool queryItemIdFromList(int itemId);
    ///
    /// \brief deleteItemListData   从列表中删除应用
    /// \param id   应用的 id
    ///
    bool deleteItemListData(int id);
    ///
    /// \brief deletePageData   删除页数据
    /// \param id   页的 id
    ///
    bool deletePageData(int id);

    bool deleteSet(int setId);    

    ///
    /// \brief 删除表中所有数据
    /// \param tableName 数据表名字
    /// \return 删除成功 or 删除失败
    ///
    bool deleteTableAllData(const QString &tableName);
    ///
    /// \brief checkTables：检查所有表是否存在
    /// \return
    ///
    bool checkTables();
    ///
    /// \brief firstInit：返回firstInit的值
    /// \return
    ///
    bool firstInited();

private:
    struct ItemDetail {
        int itemId;
        QString desktopName;
        QString name;
        QString iconName;
        int type;
        QString placeholder;
        QString categories;
    };

    ///
    /// \brief createItemsData：创建默认的 item 数据
    ///
    void createItemsData();

    ///
    /// \brief isTableExist：判断数据表是否存在
    /// \param tableName：表的名字
    /// \return 存在 or 不存在
    ///
    bool isTableExist(const QString &tableName);
    void checkSetsTableFields();

    bool addItemToItemList(const QMap<QString, QVariant> &itemDetails);
    bool addItemToSets(const QMap<QString, QVariant> &itemDetails);
    ItemDetail queryItemDetailsFromItemListTable(const QSqlQuery &query) const;

    std::tuple<int, QString> queryItemDetailsFromPageTable(const QSqlQuery &query) const;
    std::tuple<int, QString> queryItemDetailsFromSetsTable(const QSqlQuery &query) const;
    std::tuple<bool, bool, QString> queryContainerPropertyFromSetsTable(const int containerId) const;

    bool updateHomeScreenPageTable(int pageId, const QList<int> &sequence, const char *sql);

signals:

private:
    QSqlDatabase db;
    quint32 idleItemId;
    bool firstInit = false;
};

#endif // DATABASE_H
